﻿import mx.data.encoders.Num;
class arkadium.TEAEncryption extends arkadium.EncryptionPlugin
{
	public function TEAEncryption()
	{
		super.registerAlgorithm( this, "TEA_ENCRYPTION" );
	}
	
	public function encrypt( sSourceString:String, sSourceKey:String ):String
	{
		return TEAEncrypt( sSourceString, sSourceKey );
	}
	
	public function decryptAndParse( lDecryptionObject_obj,sSourceString:String, sSourceKey:String )
	{
		super.parseVariables(lDecryptionObject_obj,TEADecrypt(sSourceString, sSourceKey ));
	}
	
	
	
	///////////////////////TEA ENCRYPTION FUNCTIONS/////////////////////
	
	/**
	* TEA (Block) Class
	* Authors : Mika Palmu
	* Licence : Use freely, giving credit when you can.
	* Website : http://www.meychi.com/
	* Version : 2.0
	*
	* Original Javascript implementation:
	* Chris Veness, Movable Type Ltd: www.movable-type.co.uk
	* Algorithm: David Wheeler & Roger Needham, Cambridge University Computer Lab
	* See http://www.movable-type.co.uk/scripts/TEAblock.html
	*/
	
	/**
	* Encrypts a string with the specified key.
	*/
	private function TEAEncrypt(src, key)
	{
		var v = charsToLongs(strToChars(src));
		var k = charsToLongs(strToChars(key));
		//trace("encrypt - Begin");
		var n = v.length;
		if (n == 0) return "";
		if (n == 1) v[n++] = 0;
		var z = v[n-1], y = v[0], delta = 0x9E3779B9, max32 = 4294967295;
		var mx, e, q = Math.floor(6+52/n), sum = 0, sum2 = 0;
		while (q-- > 0) {
			sum += delta;
			sum = sum >>> 0;  //Sasha added
			e = sum>>>2 & 3;
			
			var p:Number; // Damian
			
			for (p = 0; p<n-1; p++) {
				y = v[p+1];
				mx = (z>>>5^y<<2)+(y>>>3^z<<4)^(sum^y)+(k[p&3^e]^z);
				// Begin Sasha changes
				//z = v[p] += mx;
				mx = mx >>> 0;
				v[p] += mx;
				v[p] = v[p] >>> 0;
				z = v[p];
				// End Sasha changes
 			    //trace("sum=" + sum + " e=" + e + " y=" + y + " mx=" + mx + " z=" + z + " v[0]=" + v[0] +  " v[1]=" + v[1]);
			}
			y = v[0];
			mx = (z>>>5^y<<2)+(y>>>3^z<<4)^(sum^y)+(k[p&3^e]^z);
			// Begin Sasha changes
			//z = v[n-1] += mx;
			mx = mx >>> 0;
			v[n-1] += mx;
			v[n-1] = v[n-1] >>> 0;
			z = v[n-1];
			// End Sasha changes
			//trace("z= " + z + "  v[0]= " + v[0] +  "  v[1]= " + v[1]);
		}
		//trace("encrypt - End");
		return charsToHex(longsToChars(v));
	}

	/**
	* Decrypts a string with the specified key.
	*/
	private function TEADecrypt(src, key)
	{
		var v = charsToLongs(hexToChars(src));
		var k = charsToLongs(strToChars(key));
		var n = v.length;
		if (n == 0) return "";
		var z = v[n-1], y = v[0], delta = 0x9E3779B9;
		var mx, e, q = Math.floor(6 + 52/n), sum = q*delta;
		while (sum != 0) {
			e = sum >>> 2 & 3;
			
			var p:Number; // Damian
			
			for(p = n-1; p > 0; p--){
				z = v[p-1];
				mx = (z>>>5^y<<2)+(y>>>3^z<<4)^(sum^y)+(k[p&3^e]^z);
				y = v[p] -= mx;
			}
			z = v[n-1];
			mx = (z>>>5^y<<2)+(y>>>3^z<<4)^(sum^y)+(k[p&3^e]^z);
			y = v[0] -= mx;
			sum -= delta;
		}
		return charsToStr(longsToChars(v));
	}

	private function charsToLongs(chars)
	{
		//trace("charsToLongs -- Begin");
		var temp = new Array(Math.ceil(chars.length/4));
		for (var i = 0; i<temp.length; i++) {
			temp[i] = chars[i*4] + (chars[i*4+1]<<8) + (chars[i*4+2]<<16) + (chars[i*4+3]<<24);
			//trace(temp[i]);
		}
		//trace("charsToLongs -- End");
		return temp;
	}
	
	private function longsToChars(longs)
	{
		//trace("longsToChars -- Begin");
		var codes = new Array();
		for (var i = 0; i<longs.length; i++) {
			//trace(longs[i]);
			codes.push(longs[i] & 0xFF, longs[i]>>>8 & 0xFF, longs[i]>>>16 & 0xFF, longs[i]>>>24 & 0xFF);
		}
		//trace("longsToChars -- End");
		return codes;
	}
	
	private function charsToHex(chars)
	{
		var result = new String("");
		var hexes = new Array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");
		for (var i = 0; i<chars.length; i++) {
			result += hexes[chars[i] >> 4] + hexes[chars[i] & 0xf];
		}
		return result;
	}
	
	private function hexToChars(hex)
	{
		var codes = new Array();
		for (var i = (hex.substr(0, 2) == "0x") ? 2 : 0; i<hex.length; i+=2) {
			codes.push(parseInt(hex.substr(i, 2), 16));
		}
		return codes;
	}
	
	private function charsToStr(chars)
	{
		var result = new String("");
		for (var i = 0; i<chars.length; i++) {
			result += String.fromCharCode(chars[i]);
		}
		return result;
	}
	
	private function strToChars(str)
	{
		var codes = new Array();
		for (var i = 0; i<str.length; i++) {
			codes.push(str.charCodeAt(i));
		}
		return codes;
	}
	
}